package design_pattern

import (
	"errors"
	"fmt"
	"time"
)

func NewMessage(phrase string) Message {
	return Message(phrase)
}
func NewGreeter(m Message) Greeter {
	var grumpy bool
	if time.Now().Unix()%2 == 0 {
		grumpy = true
	}
	return Greeter{Message: m, Grumpy: grumpy}
}
func NewEvent(g Greeter) (Event, error) {
	if g.Grumpy {
		return Event{}, errors.New("could not create event: event greeter is grumpy")
	}
	return Event{Greeter: g}, nil
}

type Message string

type Greeter struct {
	Grumpy  bool
	Message Message
}

func (g Greeter) Greet() Message {
	if g.Grumpy {
		return Message("Go away!")
	}
	return g.Message
}

type Event struct {
	Greeter Greeter
}

func (e Event) Start() {
	msg := e.Greeter.Greet()
	fmt.Println(msg)
}

// var Set = wire.NewSet(SuperSet, pkg.OtherSet)

// # 接口
// func provideMyFooer() *MyFooer {
// 	b := new(MyFooer)
// 	*b = "Hello, World!"
// 	return b
// }
// func provideBar(f Fooer) string {
// 	return f.Foo()
// }
//
// type Fooer interface {
// 	Foo() string
// }
//
// type MyFooer string
//
// func (b *MyFooer) Foo() string {
// 	return string(*b)
// }
//
// type Bar string
//
// var Set = wire.NewSet(provideMyFooer, wire.Bind(new(Fooer), new(*MyFooer)), provideBar)

// # 结构体
// func ProvideFoo() *Foo {
// 	return new(Foo)
// }
// func ProvideBar() *Bar {
// 	return new(Bar)
// }

// type Foo int
// type Bar int
//
// type FooBar struct {
// 	mu    sync.Mutex `wire:"-"`
// 	MyFoo Foo
// 	MyBar Bar
// }
//
// // var Set = wire.NewSet(ProvideFoo, ProvideBar, wire.Struct(new(FooBar), "MyFoo", "MyBar"))
// // var Set = wire.NewSet(wire.Struct(new(FooBar), "*"))
// var Set = wire.NewSet(ProvideFoo, wire.Struct(new(FooBar), "MyFoo"))

// type Foo struct {
// 	X int
// }
//
// func injectFoo() Foo {
// 	wire.Build(wire.Value(Foo{X: 42}))
// 	return Foo{}
// }

// func injectReader() io.Reader {
// 	wire.Build(wire.InterfaceValue(new(io.Reader), os.Stdin))
// 	return nil
// }

// # 值
// func provideFoo() Foo {
// 	return Foo{S: "Hello, World!", N: 1, F: 3.14}
// }
//
// type Foo struct {
// 	S string
// 	N int
// 	F float64
// }
//
// func injectedMessage() string {
// 	wire.Build(provideFoo, wire.FieldsOf(new(Foo), "S"))
// 	return ""
// }

// # 清理
// func provideFile(log Logger, path Path) (*os.File, func(), error) {
// 	f, err := os.Open(string(path))
// 	if err != nil {
// 		return nil, nil, err
// 	}
// 	cleanup := func() {
// 		if err := f.Close(); err != nil {
// 			log.Log(err)
// 		}
// 	}
// 	return f, cleanup, nil
// }

// # 备用
// func injectFoo() Foo {
// 	panic(wire.Build())
// }

// type Options struct {
// 	Messages []Message
// 	Writer io.Writer
// }
//
// func NewGreeter(ctx context.Context, opts *Options) (*Greeter, error) {
// }
//
// var GreeterSet = wire.NewSet(wire.Struct(new(Options), "*"), NewGreeter)
